package com.demo.amusic.util;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Authentication {
    private static String url = "https://eid.shumaidata.com/eid/check";
    private static String appCode = "678730d8833843e6963568ff891eb2ab";

    public static AuthenticationResult send(String idcord,String name) throws IOException {
        char[] idArr = idcord.toCharArray();
        //身份证校验
        if (idcord.isEmpty() || name.isEmpty()){
            return new AuthenticationResult(false,"参数不能为空");
        }else if (idcord.length() != 18){
            return new AuthenticationResult(false,"身份证位数不正确");
        }else{
            // 校验因子
            int[] factors = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
            // 模除后的校验码
            String[] mods = new String[]{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};

            // 对身份证进行加权求和计算
            int sum = 0;
            for (int i = 0; i < idArr.length - 1; i++) {
                char item = idArr[i];
                int n = item - '0';
                sum += factors[i] * n;
            }

            // 求和数据对11取模
            int mod = sum % 11;

            // 取模后的数和身份证最后以为进行对比
            String last = mods[mod];
            String lastNumber = idArr[idArr.length - 1] + "";
            if (lastNumber.equals(last)) {
                System.out.println("身份证: " + idcord + " 合法!");
            } else {
                System.out.println("身份证: " + idcord + " 不合法!");
                return new AuthenticationResult(false,"身份证号码不合法");
            }
        }

        Map<String, String> params = new HashMap<>();
        params.put("idcard", idcord);
        params.put("name", name);
        AuthenticationResult result = postForm(appCode, url, params);
        System.out.println(result);
        return result;
    }

    /**
     * 发送
     */
    private static AuthenticationResult postForm(String appCode, String url, Map<String, String> params) throws IOException {
        final StringBuilder result = new StringBuilder();
        final AuthenticationResult result1 = new AuthenticationResult();
        FutureTask<AuthenticationResult> task = new FutureTask<AuthenticationResult>(new Callable<AuthenticationResult>() {
            @Override
            public AuthenticationResult call() throws Exception {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try {
                    URL requestUrl = new URL(url);
                    connection = (HttpURLConnection) requestUrl.openConnection();
                    connection.setRequestMethod("POST");
                    connection.setConnectTimeout(8000);//链接超时
                    connection.setReadTimeout(8000);//读取超时
                    connection.setDoOutput(true);
                    connection.setDoInput(true);
                    connection.setUseCaches(false);
                    connection.setInstanceFollowRedirects(true);
                    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                    connection.setRequestProperty("Authorization", "APPCODE " + appCode);
                    DataOutputStream out = new DataOutputStream(connection
                            .getOutputStream());
                    StringBuilder request = new StringBuilder();
                    for (String key : params.keySet()) {
                        request.append(key + "=" + URLEncoder.encode(params.get(key), "UTF-8") + "&");
                    }
                    out.writeBytes(request.toString());//写入请求参数
                    out.flush();
                    out.close();

                    //开始接收数据
                    if (connection.getResponseCode() == 200) {   //请求成功，200
                        InputStream in = connection.getInputStream();
                        reader = new BufferedReader(new InputStreamReader(in));
                        String line;
                        while ((line = reader.readLine()) != null) {
                            result.append(line);
                        }
                        /**
                         * {
                         *     "code": "0", //返回码，0：成功，非0：失败（详见错误码定义）
                         *           //当code=0时，再判断下面result中的res；当code!=0时，表示调用已失败，无需再继续
                         *     "message": "成功", //返回码说明
                         *     "result": {
                         *         "name": "冯天", //姓名
                         *         "idcard": "350301198011129422", //身份证号
                         *         "res": "1", //核验结果状态码，1 一致；2 不一致；3 无记录
                         *         "description": "一致",  //核验结果状态描述
                         *        "sex": "男",
                         *         "birthday": "19940320",
                         *         "address": "江西省南昌市东湖区"
                         *     }
                         * }
                         */
                        JSONObject object = new JSONObject(result.toString());
                        if (Integer.parseInt(object.getString("code")) == 0){
                            JSONObject object1 = new JSONObject(object.getString("result"));
                            if (object1.getString("res").equals("1")){
                                result1.setPass(true);
                                result1.setMsg(object.getString("message"));
                            }else if (object1.getString("res").equals("2")){
                                result1.setPass(false);
                                result1.setMsg("核验失败，身份不一致");
                            }else if (object1.getString("res").equals("3")){
                                result1.setPass(false);
                                result1.setMsg("核验结果无记录");
                            }else {
                                result1.setPass(false);
                                result1.setMsg("认证失败，res其他");
                            }
                        }else{
                            result1.setPass(false);
                            result1.setMsg(object.getString("message"));
                        }
                    }else{    //请求失败， 400。。。
                        InputStream in = connection.getErrorStream();
                        reader = new BufferedReader(new InputStreamReader(in));
                        String line;
                        while ((line = reader.readLine()) != null) {
                            result.append(line);
                        }
                        JSONObject object = new JSONObject(result.toString());
                        result1.setMsg(object.getString("message"));
                        result1.setPass(false);
                    }
                } catch (Exception e) { //出错
                    e.printStackTrace();
                    result1.setMsg(e.getMessage());
                    result1.setPass(false);
                } finally {  //释放资源
                    if (reader != null) {
                        reader.close();//关闭流
                    }
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
                return result1;
            }
        });


        new Thread(task).start();
        try {
            AuthenticationResult result2 = task.get();
            return result2;
        } catch (Exception e) {
            e.printStackTrace();
            return new AuthenticationResult(false,"系统错误");
        }
    }

    /**
     * 认证返回类
     */
    public static class AuthenticationResult{
        public Boolean pass;
        public String msg;

        public AuthenticationResult(){

        }

        public AuthenticationResult(Boolean pass,String msg){
            this.pass = pass;
            this.msg = msg;
        }

        public Boolean getPass() {
            return pass;
        }

        public void setPass(Boolean pass) {
            this.pass = pass;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

}
